﻿/*
 *author:keily ,department 2,wuda geo
 *create date:2013-1-24
 *description:类型转换公有类
 */


using System;
using System.Text;


namespace GeoWeb.Common
{
    public sealed class ConvertHelper
    {
        /// <summary>
        /// 将对象转换为 目标类型 的值
        /// </summary>
        /// <param name="data">对象</param>
        /// <param name="targetType">目标类型</param>
        /// <returns>返回值</returns>
        public static object ConvertTo(object data, Type targetType)
        {
            if (data == null || Convert.IsDBNull(data))
            {
                return null;
            }
            Type type = data.GetType();
            if (targetType == type)
            {
                return data;
            }
            if ((targetType != typeof(Guid) && targetType != typeof(Guid?)) || type != typeof(string))
            {
                if (targetType.IsEnum)
                {
                    try
                    {
                        object result = Enum.Parse(targetType, data.ToString(), true);
                        return result;
                    }
                    catch
                    {
                        object result = Enum.ToObject(targetType, data);
                        return result;
                    }
                }
                if (targetType.IsGenericType)
                {
                    targetType = targetType.GetGenericArguments()[0];
                }

                return Convert.ChangeType(data, targetType);
            }
            if (string.IsNullOrEmpty(data.ToString()))
            {
                return null;
            }
            else if (data.ToString().Trim().Length == 36)
            {
                return new Guid(data.ToString());
            }
            else
            {
                return null;
            }
        }
        /// <summary>
        /// 对象拆箱
        /// 适用于 比如 DB.string 到 string，DB.int32 到 int32等
        /// 建议数据库类型的值到csharp类型的值转换时用
        /// </summary>
        /// <typeparam name="T">对象</typeparam>
        /// <param name="data"></param>
        /// <returns></returns>
        public static T ConvertTo<T>(object data)
        {
            if (data == null || Convert.IsDBNull(data))
            {
                return default(T);
            }
            object obj = ConvertTo(data, typeof(T));
            if (obj == null)
            {
                return default(T);
            }
            return (T)((object)obj);
        }

        public delegate bool TryParseDelegate<T>(string s, out T result);
        /// <summary>
        /// 转换数据，如果数据为null则赋值为null
        /// 调用方式如： 
        /// string strDt='2012-1-1'; 
        /// DateTime？ dt=null; 
        /// TryParseNullable<DateTime>(strDt,out dt,DateTime.TryParse)
        /// </summary>
        /// <typeparam name="T">对象类型</typeparam>
        /// <param name="s">需要转换的字符串</param>
        /// <param name="result">输入结果</param>
        /// <param name="tryParse">转换函数</param>
        public static void TryParseNullable<T>(string s, out Nullable<T> result, TryParseDelegate<T> tryParse) where T : struct
        {
            if (string.IsNullOrEmpty(s))
            {
                result = null;
                //return true;
            }
            else
            {
                T data;
                //bool success = tryParse(s, out temp);
                //result = temp;
                result = tryParse(s, out data) ? data : (Nullable<T>)null;
                //return success;
            }
        }

        /// <summary>
        /// 将M类型的实例转换为T类型，转换失败返回T类型的默认值
        /// 返回T类型值
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="M"></typeparam>
        /// <param name="dest"></param>
        /// <returns></returns>
        public static T GenericCast<T, M>(M dest)
        {
            if (null == dest)
                return default(T);

            try
            {
                if (!typeof(T).IsGenericType)
                    return (T)Convert.ChangeType(dest, typeof(T));
                else
                {
                    Type _typeGenericDefinition = typeof(T).GetGenericTypeDefinition();
                    if (_typeGenericDefinition == typeof(Nullable<>))
                    {
                        return (T)Convert.ChangeType(dest, Nullable.GetUnderlyingType(typeof(T)));
                    }
                    else
                        return default(T);
                }
            }
            catch
            {
                return default(T);
            }
        }


        #region 不太常用
        /// <summary>
        /// 进制转换，包括：2,8,10,16进制类型
        /// </summary>
        /// <param name="value">值</param>
        /// <param name="from">源进制类型：2,8,10,16</param>
        /// <param name="to">目标进制类型：2,8,10,16</param>
        /// <returns>值</returns>
        public static string ConvertBase(string value, int from, int to)
        {
            if (!IsBaseNumber(from))
            {
                throw new ArgumentException("参数from只能是2,8,10,16四个值。");
            }
            if (!IsBaseNumber(to))
            {
                throw new ArgumentException("参数to只能是2,8,10,16四个值。");
            }
            int value2 = Convert.ToInt32(value, from);
            string text = Convert.ToString(value2, to);
            if (to == 2)
            {
                switch (text.Length)
                {
                    case 3:
                        text = "00000" + text;
                        break;
                    case 4:
                        text = "0000" + text;
                        break;
                    case 5:
                        text = "000" + text;
                        break;
                    case 6:
                        text = "00" + text;
                        break;
                    case 7:
                        text = "0" + text;
                        break;
                }
            }
            return text;
        }
        private static bool IsBaseNumber(int baseNumber)
        {
            return baseNumber == 2 || baseNumber == 8 || baseNumber == 10 || baseNumber == 16;
        }

        #region string convert
        /// <summary>
        /// 将以默认的ansi编码转换字符串为byte数组
        /// </summary>
        /// <param name="text">字符串</param>
        /// <returns></returns>
        public static byte[] StringToBytes(string text)
        {
            return Encoding.Default.GetBytes(text);
        }
        /// <summary>
        /// 将以默认的ansi编码转换字符串为byte数组
        /// </summary>
        /// <param name="text">字符串</param>
        /// <param name="encoding">编码方式</param>
        /// <returns></returns>
        public static byte[] StringToBytes(string text, Encoding encoding)
        {
            return encoding.GetBytes(text);
        }
        /// <summary>
        /// 以ansi编码方式将byte数组转换为字符串
        /// </summary>
        /// <param name="bytes">byte数组</param>
        /// <returns></returns>
        public static string BytesToString(byte[] bytes)
        {
            return Encoding.Default.GetString(bytes);
        }

        /// <summary>
        /// 以指定编码方式将byte数组转换为字符串
        /// </summary>
        /// <param name="bytes">byte数组</param>
        /// <param name="encoding">编码方式</param>
        /// <returns></returns>
        public static string BytesToString(byte[] bytes, Encoding encoding)
        {
            return encoding.GetString(bytes);
        }
        #endregion

        #region int convert
        /// <summary>
        /// 将byte数组转换为32位的int
        /// </summary>
        /// <param name="data">byte数组</param>
        /// <returns></returns>
        public static int BytesToInt32(byte[] data)
        {
            if (data.Length < 4)
            {
                return 0;
            }
            int result = 0;
            if (data.Length >= 4)
            {
                byte[] array = new byte[4];
                //32bit 的int只占4个字节，所以只取偏移量开始的前4个字节
                Buffer.BlockCopy(data, 0, array, 0, 4);
                result = BitConverter.ToInt32(array, 0);
            }
            return result;
        }
        /// <summary>
        /// 将对象转换为int型
        /// </summary>
        /// <typeparam name="T">转换对象</typeparam>
        /// <param name="data">转换实例</param>
        /// <param name="defValue">转换失败时默认输出值</param>
        /// <returns></returns>
        public static int ToInt32<T>(T data, int defValue) where T : class
        {
            if (data == null || Convert.IsDBNull(data))
            {
                return defValue;
            }
            int result;
            try
            {
                result = Convert.ToInt32(data);
            }
            catch
            {
                result = defValue;
            }
            return result;
        }
        /// <summary>
        /// 将对象转换为int型,转换失败时默认输出值0
        /// </summary>
        /// <typeparam name="T">转换对象</typeparam>
        /// <param name="data">转换实例</param>
        /// <returns></returns>
        public static int ToInt32<T>(T data) where T : class
        {
            return ToInt32<T>(data, 0);
        }
        /// <summary>
        /// 字符串转换为int32
        /// </summary>
        /// <param name="data">转换值</param>
        /// <param name="defValue">转换失败时默认输出值</param>
        /// <returns></returns>
        public static int ToInt32(string data, int defValue)
        {
            if (string.IsNullOrEmpty(data))
            {
                return defValue;
            }
            int result;
            if (int.TryParse(data, out result))
            {
                return result;
            }
            return defValue;
        }
        /// <summary>
        /// 将对象转换为int32
        /// </summary>
        /// <param name="data">转换对象</param>
        /// <param name="defValue">转换失败时默认输出值</param>
        /// <returns></returns>
        public static int ToInt32(object data, int defValue)
        {
            if (data == null || Convert.IsDBNull(data))
            {
                return defValue;
            }
            int result;
            try
            {
                result = Convert.ToInt32(data);
            }
            catch
            {
                result = defValue;
            }
            return result;
        }

        #endregion

        #region boolean convert
        /// <summary>
        /// 将对象转换为bool值
        /// </summary>
        /// <typeparam name="T">对象类型</typeparam>
        /// <param name="data">对象实例</param>
        /// <param name="defValue">转换失败时默认输出值</param>
        /// <returns></returns>
        public static bool ToBoolean<T>(T data, bool defValue) where T : class
        {
            if (data == null || Convert.IsDBNull(data))
            {
                return defValue;
            }
            bool result;
            try
            {
                result = Convert.ToBoolean(data);
            }
            catch
            {
                result = defValue;
            }
            return result;
        }
        /// <summary>
        /// 将对象转换为bool值,转换失败时默认输出值false
        /// </summary>
        /// <typeparam name="T">对象类型</typeparam>
        /// <param name="data">对象实例</param>
        /// <returns></returns>
        public static bool ToBoolean<T>(T data) where T : class
        {
            return ToBoolean<T>(data, false);
        }
        /// <summary>
        /// 将值转换为bool值
        /// </summary>
        /// <param name="data">转换值</param>
        /// <param name="defValue">转换失败时默认输出值</param>
        /// <returns></returns>
        public static bool ToBoolean(string data, bool defValue)
        {
            if (string.IsNullOrEmpty(data))
            {
                return defValue;
            }
            bool result;
            if (bool.TryParse(data, out result))
            {
                return result;
            }
            return defValue;
        }
        /// <summary>
        /// 将对象转换为bool值
        /// </summary>
        /// <param name="data">转换对象</param>
        /// <param name="defValue">转换失败时默认输出值</param>
        /// <returns></returns>
        public static bool ToBoolean(object data, bool defValue)
        {
            if (data == null || Convert.IsDBNull(data))
            {
                return defValue;
            }
            bool result;
            try
            {
                result = Convert.ToBoolean(data);
            }
            catch
            {
                result = defValue;
            }
            return result;
        }
        #endregion

        #region float convert
        /// <summary>
        /// 将对象转换为浮点值
        /// </summary>
        /// <typeparam name="T">转换对象</typeparam>
        /// <param name="data">转换实例</param>
        /// <param name="defValue">转换失败时默认输出值</param>
        /// <returns></returns>
        public static float ToFloat<T>(T data, float defValue) where T : class
        {
            if (data == null || Convert.IsDBNull(data))
            {
                return defValue;
            }
            float result;
            try
            {
                result = Convert.ToSingle(data);
            }
            catch
            {
                result = defValue;
            }
            return result;
        }
        /// <summary>
        /// 将对象转换为浮点值,转换失败时默认输出值0
        /// </summary>
        /// <typeparam name="T">转换对象</typeparam>
        /// <param name="data">转换实例</param>
        /// <returns></returns>
        public static float ToFloat<T>(T data) where T : class
        {
            return ToFloat<T>(data, 0);
        }
        /// <summary>
        /// 将对象转换为浮点值
        /// </summary>
        /// <param name="data">对象</param>
        /// <param name="defValue">转换失败时默认输出值</param>
        /// <returns></returns>
        public static float ToFloat(object data, float defValue)
        {
            if (data == null || Convert.IsDBNull(data))
            {
                return defValue;
            }
            float result;
            try
            {
                result = Convert.ToSingle(data);
            }
            catch
            {
                result = defValue;
            }
            return result;
        }
        /// <summary>
        /// 将字符串转换为浮点型值
        /// </summary>
        /// <param name="data">字符串</param>
        /// <param name="defValue">转换失败时默认输出值</param>
        /// <returns></returns>
        public static float ToFloat(string data, float defValue)
        {
            if (string.IsNullOrEmpty(data))
            {
                return defValue;
            }
            float result;
            if (float.TryParse(data, out result))
            {
                return result;
            }
            return defValue;
        }
        #endregion

        #region double convert
        /// <summary>
        /// 将对象转换为双精度型值
        /// </summary>
        /// <typeparam name="T">对象</typeparam>
        /// <param name="data">实例</param>
        /// <param name="defValue">转换失败时默认输出值</param>
        /// <returns></returns>
        public static double ToDouble<T>(T data, double defValue) where T : class
        {
            if (data == null || Convert.IsDBNull(data))
            {
                return defValue;
            }
            double result;
            try
            {
                result = Convert.ToDouble(data);
            }
            catch
            {
                result = defValue;
            }
            return result;
        }
        /// <summary>
        /// 将对象转换为双精度型值
        /// </summary>
        /// <typeparam name="T">对象</typeparam>
        /// <param name="data">实例</param>
        /// <param name="decimals">保留几位精度</param>
        /// <param name="defValue">转换失败时默认输出值</param>
        /// <returns></returns>
        public static double ToDouble<T>(T data, int decimals, double defValue) where T : class
        {
            if (data == null || Convert.IsDBNull(data))
            {
                return defValue;
            }
            double result;
            try
            {
                result = Math.Round(Convert.ToDouble(data), decimals);
            }
            catch
            {
                result = defValue;
            }
            return result;
        }
        /// <summary>
        /// 将对象转换为双精度型值,转换失败时默认输出值0
        /// </summary>
        /// <typeparam name="T">对象</typeparam>
        /// <param name="data">实例</param>
        /// <param name="decimals">保留几位精度</param>
        /// <returns></returns>
        public static double ToDouble<T>(T data, int decimals) where T : class
        {
            return ToDouble<T>(data, decimals, 0);
        }
        /// <summary>
        /// 将对象转换为双精度型值
        /// </summary>
        /// <param name="data">对象</param>
        /// <param name="defValue">转换失败时默认输出值</param>
        /// <returns></returns>
        public static double ToDouble(object data, double defValue)
        {
            if (data == null || Convert.IsDBNull(data))
            {
                return defValue;
            }
            double result;
            try
            {
                result = Convert.ToDouble(data);
            }
            catch
            {
                result = defValue;
            }
            return result;
        }
        /// <summary>
        /// 将字符串转换为双精度型值
        /// </summary>
        /// <param name="data">字符串</param>
        /// <param name="defValue">转换失败时默认输出值</param>
        /// <returns></returns>
        public static double ToDouble(string data, double defValue)
        {
            if (string.IsNullOrEmpty(data))
            {
                return defValue;
            }
            double result;
            if (double.TryParse(data, out result))
            {
                return result;
            }
            return defValue;
        }
        /// <summary>
        /// 将对象转换为双精度型值
        /// </summary>
        /// <param name="data">对象</param>
        /// <param name="decimals">保留几位精度</param>
        /// <param name="defValue">转换失败时默认输出值</param>
        /// <returns></returns>
        public static double ToDouble(object data, int decimals, double defValue)
        {
            if (data == null || Convert.IsDBNull(data))
            {
                return defValue;
            }
            double result;
            try
            {
                result = Math.Round(Convert.ToDouble(data), decimals);
            }
            catch
            {
                result = defValue;
            }
            return result;
        }
        /// <summary>
        /// 将字符串转换为双精度型值
        /// </summary>
        /// <param name="data">字符串</param>
        /// <param name="decimals">保留几位精度</param>
        /// <param name="defValue">转换失败时默认输出值</param>
        /// <returns></returns>
        public static double ToDouble(string data, int decimals, double defValue)
        {
            if (string.IsNullOrEmpty(data))
            {
                return defValue;
            }
            double value;
            if (double.TryParse(data, out value))
            {
                return Math.Round(value, decimals);
            }
            return defValue;
        }
        #endregion

        #region decimal convert
        /// <summary>
        /// 将对象转换为十进制型值
        /// </summary>
        /// <typeparam name="T">对象</typeparam>
        /// <param name="data">实例</param>
        /// <param name="defValue">转换失败时默认输出值</param>
        /// <returns></returns>
        public static decimal ToDecimal<T>(T data, decimal defValue) where T : class
        {
            if (data == null || Convert.IsDBNull(data))
            {
                return defValue;
            }
            decimal result;
            try
            {
                result = Convert.ToDecimal(data);
            }
            catch
            {
                result = defValue;
            }
            return result;
        }
        /// <summary>
        /// 将对象转换为十进制型值,转换失败时默认输出值0
        /// </summary>
        /// <typeparam name="T">对象</typeparam>
        /// <param name="data">实例</param>
        /// <returns></returns>
        public static decimal ToDecimal<T>(T data) where T : class
        {
            return ToDecimal<T>(data, 0);
        }
        /// <summary>
        /// 将对象转换为十进制型值
        /// </summary>
        /// <param name="data">对象</param>
        /// <param name="defValue">转换失败时默认输出值</param>
        /// <returns></returns>
        public static decimal ToDecimal(object data, decimal defValue)
        {
            if (data == null || Convert.IsDBNull(data))
            {
                return defValue;
            }
            decimal result;
            try
            {
                result = Convert.ToDecimal(data);
            }
            catch
            {
                result = defValue;
            }
            return result;
        }
        /// <summary>
        /// 将字符串转换为十进制型值
        /// </summary>
        /// <param name="data">字符串</param>
        /// <param name="defValue">转换失败时默认输出值</param>
        /// <returns></returns>
        public static decimal ToDecimal(string data, decimal defValue)
        {
            if (string.IsNullOrEmpty(data))
            {
                return defValue;
            }
            decimal result;
            if (decimal.TryParse(data, out result))
            {
                return result;
            }
            return defValue;
        }
        #endregion

        #region datetime convert
        /// <summary>
        /// 将对象转换为时间类型值
        /// </summary>
        /// <typeparam name="T">对象</typeparam>
        /// <param name="data">实例</param>
        /// <param name="defValue">转换失败时默认输出值</param>
        /// <returns></returns>
        public static DateTime ToDateTime<T>(T data, DateTime defValue) where T : class
        {
            if (data == null || Convert.IsDBNull(data))
            {
                return defValue;
            }
            DateTime result;
            try
            {
                result = Convert.ToDateTime(data);
            }
            catch
            {
                result = defValue;
            }
            return result;
        }
        /// <summary>
        /// 将对象转换为时间类型值,转换失败时默认输出值 当前时间
        /// </summary>
        /// <typeparam name="T">对象</typeparam>
        /// <param name="data">实例</param>
        /// <returns></returns>
        public static DateTime ToDateTime<T>(T data) where T : class
        {
            return ToDateTime<T>(data, DateTime.Now);
        }
        /// <summary>
        /// 将对象转换为时间类型值
        /// </summary>
        /// <param name="data">对象</param>
        /// <param name="defValue">转换失败时默认输出值</param>
        /// <returns></returns>
        public static DateTime ToDateTime(object data, DateTime defValue)
        {
            if (data == null || Convert.IsDBNull(data))
            {
                return defValue;
            }
            DateTime result;
            try
            {
                result = Convert.ToDateTime(data);
            }
            catch
            {
                result = defValue;
            }
            return result;
        }
        /// <summary>
        /// 将字符串转换为时间类型值
        /// </summary>
        /// <param name="data">字符串</param>
        /// <param name="defValue">转换失败时默认输出值</param>
        /// <returns></returns>
        public static DateTime ToDateTime(string data, DateTime defValue)
        {
            if (string.IsNullOrEmpty(data))
            {
                return defValue;
            }
            DateTime result;
            if (DateTime.TryParse(data, out result))
            {
                return result;
            }
            return defValue;
        }
        #endregion

        #endregion
    }
}
